﻿// Copyright (c) 2010
// by http://openlightgroup.net/

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Services;
using System;

namespace SilverlightDebateForum
{
    [WebService(Namespace = "http://OpenLightGroup.net/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class WebService : System.Web.Services.WebService
    {
        #region GetXaps
        [WebMethod(Description = "GetXaps")]
        public List<string> GetXaps(RIAAuthenticationHeader Auth)
        {
            // All users can see all .xaps
            List<string> colFiles = new List<string>();

            string FolderPath = this.Context.ApplicationInstance.Server.MapPath(@"~\DesktopModules\SilverlightDebateForum\ClientBin\");

            // Add all directories at this directory.
            DirectoryInfo objDirectoryInfo = new DirectoryInfo(FolderPath);

            foreach (var fi in objDirectoryInfo.GetFiles().Where(y => y.Extension == ".xap").OrderByDescending(x => x.Name))
            {
                if (fi.Name != "SilverlightDebate.xap")
                {
                    colFiles.Add(fi.Name);
                }
            }

            return colFiles;
        }
        #endregion

        // Web Methods

        #region GetPageOfStatements
        [WebMethod]
        // Returns Page of Statements that match the various search criteria
        public List<Statement> GetPageOfStatements(int CategoryID, DateTime? StartDate, DateTime? EndDate, string SearchText, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            return GetPageOfStatements_Ex(true, CategoryID, StartDate, EndDate, SearchText, PageSize, PageOffset, Auth);
        }
        #endregion

        #region GetPageOfStatementsWithEmptyContent
        [WebMethod]
        // Returns Page of Statements less StatementContents
        public List<Statement> GetPageOfStatementsWithEmptyContent(int CategoryID, DateTime? StartDate, DateTime? EndDate, string SearchText, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            return GetPageOfStatements_Ex(false, CategoryID, StartDate, EndDate, SearchText, PageSize, PageOffset, Auth);
        }
        #endregion

        #region GetSearchPageOfStatementsWithEmptyContent
        [WebMethod]
        public StatementsSearchResult GetSearchPageOfStatementsWithEmptyContent(int CategoryID, DateTime? StartDate, DateTime? EndDate, string SearchText, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            return GetStatements_Ex(false, CategoryID, StartDate, EndDate, SearchText, PageSize, PageOffset, Auth);
        }
        #endregion

        #region GetPageOfCategories
        [WebMethod]
        // Returns Page of Categories with matching CategoryID
        public List<Category> GetPageOfCategories(int CategoryID, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            List<Category> CategoryList = new List<Category>();

            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    CategoryList =
                    (
                        from sdCategory in db.SilverDebate_Categories
                        select new Category
                        {
                            CategoryID = sdCategory.CategoryID,
                            Title = sdCategory.Title,
                            Subtitle = sdCategory.Subtitle,
                        }
                    ).OrderBy(p => p.Title).Skip(PageOffset * PageSize).Take(PageSize).ToList();
                }
            }
            catch (System.Exception ex)
            {
                var category = new Category();
                category.CategoryID = -1;
                category.Errors.Add(ex.Message);
                CategoryList.Add(category);
            }

            return CategoryList;
        }
        #endregion

        #region GetStatement
        [WebMethod]
        // Returns Statement
        public Statement GetStatement(int statementID, RIAAuthenticationHeader Auth)
        {
            Statement statement = new Statement();

            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    statement = (from sdStatement in db.SilverDebate_Statements
                                 from sdCategory in db.SilverDebate_Categories
                                 where sdStatement.StatementID == statementID
                                 where sdCategory.CategoryID == sdStatement.CategoryID
                                 select new Statement
                                  {
                                      StatementID = sdStatement.StatementID,
                                      CategoryID = sdStatement.CategoryID,
                                      CategoryTitle = sdCategory.Title,
                                      CreatedBy = sdStatement.CreatedBy,
                                      Title = sdStatement.Title,
                                      StatementContent = sdStatement.StatementContent,
                                      PostedBy = sdStatement.PostedBy,
                                      Locked = sdStatement.Locked,
                                      UpdatedOn = sdStatement.UpdatedOn,
                                      UpdatedBy = sdStatement.UpdatedBy,
                                      AgreeCount = (from sdAgrees in db.SilverDebate_Opinions
                                                    where sdAgrees.Agree == true
                                                    where sdAgrees.StatementID == sdStatement.StatementID
                                                    select sdAgrees.SilverDebate_Activities.Count).Sum(),
                                      DisagreeCount = (from sdDisagrees in db.SilverDebate_Opinions
                                                       where sdDisagrees.Agree == false
                                                       where sdDisagrees.StatementID == sdStatement.StatementID
                                                       select sdDisagrees.SilverDebate_Activities.Count).Sum()
                                  }).SingleOrDefault();
                    if (statement == null)
                    {
                        statement.StatementID = -1;
                        statement.Errors.Add(String.Format("Statement {0} not Found", statementID));
                    }
                }
            }
            catch (System.Exception ex)
            {
                statement.StatementID = -1;
                statement.Errors.Add(ex.Message);
            }

            return statement;
        }
        #endregion

        #region GetSupportCountSatement
        [WebMethod]
        // Returns statement with agreeing or disagreeing votes count
        public Statement GetSupportCountSatement(Statement _statement, bool Agree, RIAAuthenticationHeader Auth)
        {
            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    var supportCount = (from sdSupportCount in db.SilverDebate_Opinions
                                        where sdSupportCount.StatementID == _statement.StatementID
                                        where sdSupportCount.Agree == Agree
                                        select sdSupportCount.SilverDebate_Activities).Count();

                    _statement.AgreeCount = supportCount;

                }
            }
            catch (System.Exception ex)
            {
                _statement.Errors.Add(ex.Message);
            }

            return _statement;
        }
        #endregion

        #region CreateNewStatement
        [WebMethod]
        //makes new statement
        public Statement CreateNewStatement(int CategoryID, string Title, string Content, RIAAuthenticationHeader Auth)
        {
            Statement _statement = new Statement();
            RIAAuthentication RIAAuth = new RIAAuthentication(Auth);
            if (RIAAuth.IsUserValid())
            {
                try
                {
                    SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext();

                    SilverDebate_Statement _objStatement = new SilverDebate_Statement();
                    _objStatement.CategoryID = CategoryID;
                    _objStatement.CreatedBy = Auth.UserID;
                    _objStatement.StatementContent = Content;
                    if (Content == null)
                    {
                        _objStatement.StatementContent = "";
                    }
                    _objStatement.Title = Title;
                    _objStatement.UpdatedBy = Auth.UserID;
                    _objStatement.UpdatedOn = DateTime.Now;
                    _objStatement.PostedBy = Auth.UserID;

                    db.SilverDebate_Statements.InsertOnSubmit(_objStatement);
                    db.SubmitChanges();

                    _statement.StatementID = _objStatement.StatementID;
                    _statement.CategoryID = _objStatement.CategoryID;
                    _statement.CreatedBy = _objStatement.CreatedBy;
                    _statement.StatementContent = _objStatement.StatementContent;
                    _statement.Title = _objStatement.Title;
                    _statement.UpdatedBy = _objStatement.UpdatedBy;
                    _statement.UpdatedOn = _objStatement.UpdatedOn;

                }
                catch (System.Exception ex)
                {
                    _statement.StatementID = -1;
                    _statement.Errors.Add(ex.Message);
                    return _statement;
                }
            }
            return _statement;
        }
        #endregion

        #region GetSupportCountOpinion
        [WebMethod]
        // Returns statement with agreeing or disagreeing votes count
        public Opinion GetSupportCountOpinion(Opinion _opinion, RIAAuthenticationHeader Auth)
        {
            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    var voteCount = (from sdSupportCount in db.SilverDebate_Activities
                                     where sdSupportCount.OpinionID == _opinion._OpinionID
                                     select sdSupportCount).Count();

                    _opinion._SupportCount = voteCount;

                }
            }
            catch (System.Exception ex)
            {
                _opinion.Errors.Add(ex.Message);
            }

            return _opinion;
        }
        #endregion

        #region GetOpinions
        [WebMethod]
        // Returns page of Opinions with matching StatementID for a single side
        public List<Opinion> GetOpinions(int statementID, bool Agree, RIAAuthenticationHeader Auth)
        {
            List<Opinion> opinionsList = new List<Opinion>();

            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    opinionsList = (from sdOpinions in db.SilverDebate_Opinions
                                    where sdOpinions.StatementID == statementID
                                    where sdOpinions.Agree == Agree
                                    select new Opinion
                                    {
                                        _OpinionID = sdOpinions.OpinionID,
                                        _StatementID = statementID,
                                        _Agree = Agree,
                                        _Title = sdOpinions.Title,
                                        _PostedBy = sdOpinions.PostedBy,
                                        _UpdatedOn = sdOpinions.UpdatedOn,
                                        _SupportCount = (from sdSupports in db.SilverDebate_Activities
                                                         where sdSupports.OpinionID == sdOpinions.OpinionID
                                                         select sdSupports).Count()
                                    }
                                    ).OrderByDescending(x => x._SupportCount).ToList();

                }
            }
            catch (System.Exception ex)
            {
                var opinion = new Opinion();
                opinion._StatementID = -1;
                opinion._OpinionID = -1;
                opinion.Errors.Add(ex.Message);
                opinionsList.Add(opinion);
            }

            return opinionsList;
        }
        #endregion

        #region CanVote
        [WebMethod]
        //check for activity
        public bool CanVote(int StatementID, RIAAuthenticationHeader Auth)
        {
            bool _canVote = false;

            RIAAuthentication RIAAuth = new RIAAuthentication(Auth);
            if (RIAAuth.IsUserValid())
            {
                try
                {
                    using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                    {
                        var _Activity = (from sdActivity in db.SilverDebate_Activities
                                         where sdActivity.StatementID == StatementID
                                         where sdActivity.UserID == Auth.UserID
                                         select sdActivity).FirstOrDefault();

                        //no activity add to support
                        if (_Activity == null)
                        {
                            _canVote = true;
                        }
                    }
                }
                catch
                {
                    //only return bool
                }
            }

            return _canVote;
        }
        #endregion

        #region SupportOpinion
        [WebMethod]
        //supports an opinion if they have not supported the opinion yet.
        public Opinion SupportOpinion(int statementID, int OpinionID, RIAAuthenticationHeader Auth)
        {
            Opinion _opinion = new Opinion();
            RIAAuthentication RIAAuth = new RIAAuthentication(Auth);
            if (RIAAuth.IsUserValid())
            {
                try
                {
                    using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                    {
                        var _Activity = (from sdActivity in db.SilverDebate_Activities
                                         where sdActivity.StatementID == statementID
                                         where sdActivity.UserID == Auth.UserID
                                         select sdActivity).FirstOrDefault();

                        var _Opinion = (from sdOp in db.SilverDebate_Opinions
                                        where sdOp.OpinionID == OpinionID
                                        select sdOp).FirstOrDefault();

                        //no activity add to support
                        if (_Activity == null && _Opinion != null)
                        {
                            SilverDebate_Activity _activity = new SilverDebate_Activity();
                            _activity.StatementID = statementID;
                            _activity.UserID = Auth.UserID;
                            _activity.OpinionID = OpinionID;

                            db.SilverDebate_Activities.InsertOnSubmit(_activity);

                            _Opinion.SilverDebate_Statement.UpdatedBy = Auth.UserID;
                            _Opinion.SilverDebate_Statement.UpdatedOn = DateTime.Now;

                            db.SubmitChanges();
                        }

                        _opinion = (from sdOpinions in db.SilverDebate_Opinions
                                    where sdOpinions.OpinionID == OpinionID
                                    select new Opinion
                                    {
                                        _OpinionID = sdOpinions.OpinionID,
                                        _Agree = sdOpinions.Agree,
                                        _PostedBy = sdOpinions.PostedBy,
                                        _StatementID = sdOpinions.StatementID,
                                        _Title = sdOpinions.Title,
                                        _UpdatedOn = sdOpinions.UpdatedOn,
                                        _SupportCount = (from sdSupports in db.SilverDebate_Activities
                                                         where sdSupports.OpinionID == sdOpinions.OpinionID
                                                         select sdSupports).Count()
                                    }).FirstOrDefault();

                    }
                }
                catch (System.Exception ex)
                {
                    _opinion._StatementID = -1;
                    _opinion._OpinionID = -1;
                    _opinion.Errors.Add(ex.Message);
                }
            }

            return _opinion;
        }

        #endregion

        #region CreateNewOpinion
        [WebMethod]
        //makes a new opinion
        public Opinion CreateNewOpinion(int statementID, RIAAuthenticationHeader Auth, bool Agree, string Title)
        {
            Opinion _opinion = new Opinion();
            RIAAuthentication RIAAuth = new RIAAuthentication(Auth);
            if (RIAAuth.IsUserValid())
            {
                try
                {
                    using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                    {
                        var _Activity = (from sdActivity in db.SilverDebate_Activities
                                         where sdActivity.StatementID == statementID
                                         where sdActivity.UserID == Auth.UserID
                                         select sdActivity).FirstOrDefault();

                        var _Statement = (from sdStatement in db.SilverDebate_Statements
                                          where sdStatement.StatementID == statementID
                                          select sdStatement).FirstOrDefault();

                        //no activity can make new opinion
                        if (_Activity == null && _Statement != null)
                        {
                            SilverDebate_Opinion _objOpinion = new SilverDebate_Opinion();
                            _objOpinion.Agree = Agree;
                            _objOpinion.PostedBy = Auth.UserID;
                            _objOpinion.StatementID = statementID;
                            _objOpinion.Title = Title;
                            _objOpinion.UpdatedOn = DateTime.Now;
                            _objOpinion.UpdatedBy = Auth.UserID;

                            db.SilverDebate_Opinions.InsertOnSubmit(_objOpinion);
                            db.SubmitChanges();

                            _opinion._Agree = _objOpinion.Agree;
                            _opinion._OpinionID = _objOpinion.OpinionID;
                            _opinion._PostedBy = _objOpinion.PostedBy;
                            _opinion._StatementID = _objOpinion.StatementID;
                            _opinion._Title = _objOpinion.Title;
                            _opinion._UpdatedOn = _objOpinion.UpdatedOn;

                            SilverDebate_Activity _activity = new SilverDebate_Activity();
                            _activity.StatementID = statementID;
                            _activity.UserID = Auth.UserID;
                            _activity.OpinionID = _objOpinion.OpinionID;

                            db.SilverDebate_Activities.InsertOnSubmit(_activity);

                            //update statement stat
                            _Statement.UpdatedOn = DateTime.Now;
                            _Statement.UpdatedBy = Auth.UserID;

                            db.SubmitChanges();
                        }

                    }
                }
                catch (System.Exception ex)
                {
                    _opinion._StatementID = -1;
                    _opinion._OpinionID = -1;
                    _opinion.Errors.Add(ex.Message);
                }
            }

            return _opinion;
        }

        #endregion

        #region ResetVote
        [WebMethod]
        //deletes activity
        public bool ResetVote(int statementID, RIAAuthenticationHeader Auth)
        {
            RIAAuthentication RIAAuth = new RIAAuthentication(Auth);
            if (RIAAuth.IsUserValid())
            {
                try
                {
                    SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext();

                    var _Activity = (from sdActivity in db.SilverDebate_Activities
                                     where sdActivity.StatementID == statementID
                                     where sdActivity.UserID == Auth.UserID
                                     select sdActivity).FirstOrDefault();

                    var _Statement = (from sdStatement in db.SilverDebate_Statements
                                      where sdStatement.StatementID == statementID
                                      select sdStatement).FirstOrDefault();

                    if (_Activity != null && _Statement != null)
                    {
                        //update statement stat
                        _Statement.UpdatedOn = DateTime.Now;
                        _Statement.UpdatedBy = Auth.UserID;

                        db.SilverDebate_Activities.DeleteOnSubmit(_Activity);

                        //clear the opinion, if 1 this is the only one.
                        if (_Activity.SilverDebate_Opinion.SilverDebate_Activities.Count == 1)
                        {
                            db.SilverDebate_Opinions.DeleteOnSubmit(_Activity.SilverDebate_Opinion);
                        }

                        db.SubmitChanges();
                    }
                    return true;


                }
                catch (System.Exception ex)
                {
                    //todo 
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region GetCategories
        [WebMethod]
        public List<Category> GetCategories(RIAAuthenticationHeader Auth)
        {
            // Make an empty collection so that something will always be returned
            List<Category> colCategory = new List<Category>();

            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    var theCategories = from categories in db.SilverDebate_Categories
                                        orderby categories.Title
                                        select categories;

                    foreach (var category in theCategories)
                    {
                        Category cat = new Category();
                        cat.CategoryID = category.CategoryID;
                        cat.Title = category.Title;
                        cat.Subtitle = category.Subtitle;
                        colCategory.Add(cat);
                    }
                }
            }
            catch (System.Exception ex)
            {
                // If there are errors, add them to the response
                Category cat = new Category();
                cat.CategoryID = -1;
                cat.Errors.Add(ex.Message);
                colCategory.Add(cat);
            }

            // Return the response
            return colCategory;
        }
        #endregion

        #region GetNews
        [WebMethod]
        public List<News> GetNews(RIAAuthenticationHeader Auth)
        {
            List<News> colNews = new List<News>();

            return colNews;
        }
        #endregion

        #region GetOpinion
        [WebMethod]
        public List<Opinion> GetOpinion(RIAAuthenticationHeader Auth)
        {
            List<Opinion> colOpinion = new List<Opinion>();

            return colOpinion;
        }
        #endregion

        #region GetOpinionSupport
        [WebMethod]
        public List<OpinionSupport> GetOpinionSupport(RIAAuthenticationHeader Auth)
        {
            List<OpinionSupport> colOpinionSupport = new List<OpinionSupport>();

            return colOpinionSupport;
        }
        #endregion

        #region GetUserInfo
        [WebMethod]
        public List<UserInfo> GetUserInfo(RIAAuthenticationHeader Auth)
        {
            List<UserInfo> colUserInfo = new List<UserInfo>();

            return colUserInfo;
        }
        #endregion

        #region Private Methods

        #region GetStatementOpinions
        private List<Opinion> GetStatementOpinions(int StatementID, bool Agree)
        {
            using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
            {
                return (from opinions in db.SilverDebate_Opinions
                        where opinions.StatementID == StatementID &&
                                opinions.Agree == Agree ? true : false
                        select new Opinion
                        {
                            _OpinionID = opinions.OpinionID,
                            _Agree = opinions.Agree,
                            _Title = opinions.Title,
                            _StatementID = opinions.StatementID,
                            _PostedBy = opinions.PostedBy,
                            _SupportCount = (from support in db.SilverDebate_Activities
                                             where support.OpinionID == opinions.OpinionID
                                             select support).Count(),
                            _UpdatedOn = opinions.UpdatedOn
                        }).ToList();
            }
        }
        #endregion

        #region GetStatements_Ex

        private StatementsSearchResult GetStatements_Ex(bool IncludeContent, int CategoryID, DateTime? StartDate, DateTime? EndDate, string SearchText, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            StatementsSearchResult result = new StatementsSearchResult();

            List<Statement> statementList = new List<Statement>();

            try
            {
                using (SilverlightDebateForumDBDataContext db = new SilverlightDebateForumDBDataContext())
                {
                    var candidates = from sdStatement in db.SilverDebate_Statements
                                     select sdStatement;

                    if (CategoryID != -1)
                        candidates = candidates.Where(p => p.CategoryID == CategoryID).OrderByDescending(x => x.UpdatedOn);

                    if (StartDate.HasValue)
                        candidates = candidates.Where(p => p.UpdatedOn.Date >= StartDate.Value.Date);

                    if (EndDate.HasValue)
                        candidates = candidates.Where(p => p.UpdatedOn.Date <= EndDate.Value.Date);

                    if (String.IsNullOrEmpty(SearchText) == false)
                        candidates = candidates.Where(p => p.StatementContent.ToUpper().Contains(SearchText.ToUpper()) ||
                                                        p.Title.ToUpper().Contains(SearchText.ToUpper()));
                    int nCount = candidates.Count();

                    result.TotalPages = nCount / PageSize;
                    if (nCount % PageSize != 0)
                        result.TotalPages++;
                    result.CurrentPage = PageOffset + 1;
                    result.RecordsPerPage = PageSize;

                    result.StatementList =
                    (
                        from sdStatement in candidates
                        from sdCategory in db.SilverDebate_Categories
                        where sdCategory.CategoryID == sdStatement.CategoryID
                        select new Statement
                        {
                            StatementID = sdStatement.StatementID,
                            CategoryID = sdStatement.CategoryID,
                            CategoryTitle = sdCategory.Title,
                            CreatedBy = sdStatement.CreatedBy,
                            Title = sdStatement.Title,
                            AgreeCount = (from sdAgrees in db.SilverDebate_Opinions
                                          where sdAgrees.Agree == true
                                          where sdAgrees.StatementID == sdStatement.StatementID
                                          select sdAgrees.SilverDebate_Activities.Count).Sum() as int? ?? 0,
                            DisagreeCount = (from sdAgrees in db.SilverDebate_Opinions
                                             where sdAgrees.Agree == false
                                             where sdAgrees.StatementID == sdStatement.StatementID
                                             select sdAgrees.SilverDebate_Activities.Count).Sum() as int? ?? 0,
                            StatementContent = IncludeContent ? sdStatement.StatementContent : string.Empty,
                            PostedBy = sdStatement.PostedBy,
                            Locked = sdStatement.Locked,
                            UpdatedOn = sdStatement.UpdatedOn,
                            UpdatedBy = sdStatement.UpdatedBy,
                            AgreeOpinions = GetStatementOpinions(sdStatement.StatementID, true),
                            DisagreeOpinions = GetStatementOpinions(sdStatement.StatementID, false)
                        }
                    ).OrderByDescending(p => p.UpdatedOn).Skip(PageOffset * PageSize).Take(PageSize).ToList();
                }
            }
            catch (System.Exception ex)
            {
                var statement = new Statement();
                statement.StatementID = -1;
                statement.Errors.Add(ex.Message);
            }

            return result;
        }

        private List<Statement> GetPageOfStatements_Ex(bool IncludeContent, int CategoryID, DateTime? StartDate, DateTime? EndDate, string SearchText, int PageSize, int PageOffset, RIAAuthenticationHeader Auth)
        {
            StatementsSearchResult result = GetStatements_Ex(IncludeContent, CategoryID, StartDate, EndDate, SearchText, PageSize, PageOffset, Auth);
            return result.StatementList;
        }

        #endregion Private Methods

        #endregion

    }
}
